package com.cat.recruit.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.cat.recruit.bean.dto.AppointmentSlotDTO;
import com.cat.recruit.bean.dto.UserDTO;
import com.cat.recruit.common.constant.UserStatus;
import com.cat.recruit.common.exception.BusinessException;
import com.cat.recruit.common.exception.BusinessExceptionEnum;
import com.cat.recruit.common.result.Result;
import com.cat.recruit.config.JwtUserDetails;
import com.cat.recruit.entity.AppointmentSlot;
import com.cat.recruit.entity.User;
import com.cat.recruit.entity.UserAppointment;
import com.cat.recruit.mapper.AppointmentSlotMapper;
import com.cat.recruit.mapper.UserAppointmentMapper;
import com.cat.recruit.mapper.UserMapper;
import com.cat.recruit.service.UserService;
import com.cat.recruit.util.JwtUtils;
import com.cat.recruit.util.StateUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.cat.recruit.common.exception.BusinessException.bizException;


@Service
@Transactional(
        // 事务传播属性
        propagation = Propagation.REQUIRED,
        // 事务隔离属性
        isolation = Isolation.READ_COMMITTED,
        // 所有异常都回滚
        rollbackFor = Exception.class,
        // 10秒超时
        timeout = 10
)
public class UserServiceImpl implements UserService {
    //TODO: 优化抛异常逻辑，使得userMapper抛异常能尽量抛业务异常

    private final String appId;
    private final String appSecret;
    private final UserMapper userMapper;
    private final JwtUserDetailsServiceImpl jwtUserDetailsService;
    private final JwtUtils jwtUtils;
    private final UserAppointmentMapper userAppointmentMapper;
    private final AppointmentSlotMapper appointmentSlotMapper;

    // 构造器注入
    // 问了ai说这样注入好一点，你要不看看把你的那些代码也改成这样
    public UserServiceImpl(
            @Value("${wx.appid}") String appId,
            @Value("${wx.secret}") String appSecret,
            UserMapper userMapper,
            JwtUserDetailsServiceImpl jwtUserDetailsService, JwtUtils jwtUtils, UserAppointmentMapper userAppointmentMapper, AppointmentSlotMapper appointmentSlotMapper) {
        this.appId = appId;
        this.appSecret = appSecret;
        this.userMapper = userMapper;
        this.jwtUserDetailsService = jwtUserDetailsService;
        this.jwtUtils = jwtUtils;
        this.userAppointmentMapper = userAppointmentMapper;
        this.appointmentSlotMapper = appointmentSlotMapper;
    }

//    // 从配置文件里读取 appid 和 secret
//    @Value("${wx.appid}")
//    private String appId;
//
//    @Value("${wx.secret}")
//    private String appSecret;
//
//    @Autowired
//    private UserMapper userMapper;
//
//    @Autowired
//    JwtUserDetailsServiceImpl jwtUserDetailsService;

    /**
     * 用户的登录功能
     * @param code
     * @return
     */
    @Override
    public Result login(String code) {
//        // 拼接请求url
//        String url = String.format(
//                "https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code",
//                appId, appSecret, code
//        );
//
//        // 发送 GET 请求
//        RestTemplate restTemplate = new RestTemplate();
//        String response = restTemplate.getForObject(url, String.class);
//
//        // 使用 Fastjson 解析返回结果
//        JSONObject json = JSON.parseObject(response);
//
//        if (json.containsKey("errcode")) {
//            throw bizException(BusinessExceptionEnum.CODE_INVALID);
//        }
//        String openId = json.getString("openid");
//        String sessionKey = json.getString("session_key");
        String openId = "123456";
        User user = userMapper.selectByOpenId(openId);
        if(user != null){
            // 生成token
            Map<String, Object> data = getUserTokenMap(user);
            return Result.success(data);
        }else {
            User newUser = createUser(openId);
            Map<String, Object> data = getUserTokenMap(newUser);
            return Result.success(data);
        }
    }

    @Override
    public User createUser(String openId) {
        User user = new User();
        user.setOpenId(openId);
        user.setRole("user");
        user.setState("未报名");
        if (userMapper.insert(user) > 0) {
            return user;
        }else {
            throw bizException(BusinessExceptionEnum.INSERT_FAILED);
        }
    }

    /**
     * 用户获取自己注册信息
     * @param openId
     * @return
     */
    @Override
    public Result getInformation(String openId) {
        User user = userMapper.selectByOpenId(openId);
        UserDTO userDTO = new UserDTO(user);
        return Result.success(userDTO);
    }


    /**
     * 用户预约面试方法
     * 感觉前端传来了很多没用的数据
     * @return 成功或失败
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result bookInterview(Integer appointmentId, String token) {
        // 查询预约人数是否超过限制
        int available = appointmentSlotMapper.hasCapacity(appointmentId);
        if (available == 0) {
            throw bizException(BusinessExceptionEnum.APPOINTMENT_FULL);
        }
        Integer userId = jwtUtils.getUserId(token);
        // 查询用户是否预约过
        int booked = userAppointmentMapper.hasBooked(userId);
        if (booked > 0) {
            throw bizException(BusinessExceptionEnum.ALREADY_BOOKED); // 自定义异常
        }
        // 更改users表中用户的状态为“一面”或“二面”
        String accessType = appointmentSlotMapper.getAccessTypeById(appointmentId);
        String state = UserStatus.appointedAccess(accessType);
        userMapper.updateStateById(userId,state);
        // 插入预约记录
        UserAppointment userAppointment = new UserAppointment();
        System.out.println(userId);
        userAppointment.setUserId(userId);
        userAppointment.setAppointmentId(appointmentId);
        userAppointmentMapper.insert(userAppointment);
        // 使预约数+1
        UpdateWrapper<AppointmentSlot> wrapper = new UpdateWrapper<>();
        wrapper.eq("id", appointmentId)
                .setSql("appointed_count = appointed_count + 1");
        int rows = appointmentSlotMapper.update(null, wrapper);
        if (rows == 0) {
            // 手动抛出异常，让事务回滚
            throw new RuntimeException("更新 appointed_count 失败，事务回滚！");
        }
        return Result.success();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result cancelInterview(Integer appointmentId, JwtUserDetails userDetails, String State) {
//        if (Objects.equals(State, "初面")){
//            State = "已报名";
//        }else if (Objects.equals(State, "一面")){
//            State = "一轮考核中";
//        }else if (Objects.equals(State, "二面")){
//            State = "一轮已通过";
//        }
        Integer userId = userDetails.getId();
        // 使个人预约状态回退
        //String newState = StateUtils.convert(State);
        String newState = UserStatus.cancelAccess(State);
        UpdateWrapper<User> userWrapper = new UpdateWrapper<>();
        userWrapper.eq("user_id", userId)
                .setSql("state = '" + newState + "'");
        int rows = userMapper.update(null, userWrapper);
        if (rows == 0) {
            throw bizException(BusinessExceptionEnum.UPDATE_FAILED);
        }
        // 使预约数-1
        UpdateWrapper<AppointmentSlot> wrapper = new UpdateWrapper<>();
        wrapper.eq("id", appointmentId)
                .setSql("appointed_count = appointed_count - 1");
        int newRows = appointmentSlotMapper.update(null, wrapper);
        if (newRows == 0) {
            throw bizException(BusinessExceptionEnum.UPDATE_FAILED);
        }
        // 删除个人预约记录（is_del==0）
        int cancelRows = userAppointmentMapper.cancelBookedById(userId);
        if (cancelRows == 0) {
            throw bizException(BusinessExceptionEnum.UPDATE_FAILED);
        }
        return Result.success();
    }

    /**
     * 获取预约时间
     * @return
     */
    @Override
    public Result getInterviewTime() {
        List<AppointmentSlot> appointmentSlots = appointmentSlotMapper.selectList1();
        List<AppointmentSlotDTO> appointmentSlotDTOSList = appointmentSlots.stream()
                .map(AppointmentSlotDTO::new)
                .toList();
        return Result.success(appointmentSlotDTOSList);
    }

    @Override
    public Result getAppointmentState(JwtUserDetails userDetails) {
        Integer userId = userDetails.getId();
        UserAppointment userAppointment = userAppointmentMapper.selectOne(
                new QueryWrapper<UserAppointment>()
                    .eq("user_id", userId)
                    .eq("is_del", 0)
                    .select("appointment_id")
        );
        if (userAppointment != null) {
            return Result.success(userAppointment.getAppointmentId());
        }else {
            return Result.success();
        }
    }

    /**
     * 用户报名
     *
     * @param userName         用户名
     * @param userNumber       学号
     * @param academy          学院
     * @param direction        方向
     * @param phone            手机号
     * @param email            邮箱
     * @param selfIntroduction 自我介绍
     * @param userDetails      用户详情
     * @return Result
     */
    @Override
    public Result apply(String userName, String userNumber, String academy, String direction, String phone, String email, String selfIntroduction, JwtUserDetails userDetails) {
        Integer id = userDetails.getId();
        User user = null;
        try {
            user = userMapper.selectById(userDetails.getId());
            if (user == null) {
                throw bizException(BusinessExceptionEnum.USER_NOT_EXIST);
            }
        } catch (Exception e) {
            throw bizException(BusinessExceptionEnum.INTERNAL_SERVER_ERROR);
        }
        user.setState("已报名");
        user.setName(userName);
        user.setUserNumber(userNumber);
        user.setAcademy(academy);
        user.setDirection(direction);
        user.setPhoneNumber(phone);
        user.setEmail(email);
        user.setUserIntro(selfIntroduction);

        // 更新数据库
        try {
            if (userMapper.updateById(user) > 0) {
                return Result.success();
            }else {
                throw bizException(BusinessExceptionEnum.UPDATE_FAILED);
            }
        } catch (Exception e) {
            throw bizException(BusinessExceptionEnum.INTERNAL_SERVER_ERROR);
        }
//        if (userMapper.updateById(user) > 0) {
//            return Result.success();
//        } else {
//            throw bizException(BusinessExceptionEnum.UPDATE_FAILED);
//        }
    }

    //提取的方法
    private Map<String, Object> getUserTokenMap(User user) {
        String token = jwtUserDetailsService.generateToken(user);


        // 这里改了
        String refreshToken = jwtUserDetailsService.generateRefreshToken(user);

        // 生成用户信息DTO
        UserDTO userDTO = new UserDTO(user);
        // 封装数据
        Map<String, Object> data = new HashMap<>();
        data.put("token", token);

        // 这里改了
        data.put("refreshToken", refreshToken);


        data.put("user", userDTO);
        return data;
    }

    //才发现没必要用这东西
    @Override
    public int selectUserIsExist(String openId) {
        //返回0代表改用户不存在，返回1代表该用户已存在
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("open_id", openId);
        long count = userMapper.selectCount(queryWrapper);
        if (count > 0) {
            return 1;
        } else {
            return 0;
        }
    }
}
